﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Threading;
using System.Threading;

[assembly: CLSCompliant(true)]

namespace WpfExceptionWindow
{
    /// <summary>
    /// Displays an exception window.
    /// </summary>
    public static class ExceptionWindow
    {
        private delegate ExceptionWindowResult ExceptionWindowResultDelegate();

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>
        /// <param name="owner">The window that will own the modal window.</param>
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the 
        /// title bar caption to display.</param>
        /// <param name="button">A <see cref="ExceptionWindowResult"/> value that 
        /// specifies the button or buttons to display.</param>
        /// <param name="icon">A <see cref="ExceptionWindowImage"/> value that
        /// specifies the icon to display.</param>
        /// <param name="defaultResult">A <see cref="ExceptionWindowResult"/> value
        /// that specifies the default result of the exception window.</param>
        /// <param name="options">A <see cref="ExceptionWindowOptions"/> value object that
        /// specifies the options.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Window owner,
            Exception exception,
            string caption,
            ExceptionWindowButton button,
            ExceptionWindowImage icon,
            ExceptionWindowResult defaultResult,
            ExceptionWindowOptions options)
        {
            //Check for a null exception
            if (exception == null) throw new ArgumentNullException("exception");

            ExceptionWindowResult result = defaultResult;
            //Set up to run in its own thread.
            var wndThread = new Thread(delegate()
                {
                    //Create the window
                    var wnd = new InnerExceptionWindow(owner, exception, caption, button, icon, defaultResult, options);
                    //Show as a modal dialog
                    wnd.ShowDialog();
                    //Get the result
                    result = wnd.Result;
                });

            //Must set the ApartmentState to STA.
            wndThread.SetApartmentState(ApartmentState.STA);
            //Give it a name
            wndThread.Name = "Exception Window Thread";
            //Start the Thread
            wndThread.Start();
            //Wait for the thread to finish
            wndThread.Join();

            return result;
        }

        #region Show with Owner
        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>
        /// <param name="owner">The window that will own the modal window.</param>
        /// <param name="exception">A <see cref="System.Exception"/> that specifies the information to display.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Window owner,
            Exception exception)
        {
            return Show(owner, exception, string.Format(System.Globalization.CultureInfo.CurrentCulture, "A {0} occured", exception.GetType().FullName));
        }

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="owner">The window that will own the modal window.</param>
        /// <param name="exception">A <see cref="System.Exception"/> that specifies the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the title bar caption to display.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Window owner,
            Exception exception,
            string caption)
        {
            return Show(owner, exception, caption, ExceptionWindowButton.Abort);
        }

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="owner">The window that will own the modal window.</param>
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the 
        /// title bar caption to display.</param>
        /// <param name="button">A <see cref="ExceptionWindowResult"/> value that 
        /// specifies the button or buttons to display.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Window owner,
            Exception exception,
            string caption,
            ExceptionWindowButton button)
        {
            return Show(owner, exception, caption, button, ExceptionWindowImage.None);
        }

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="owner">The window that will own the modal window.</param>
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the 
        /// title bar caption to display.</param>
        /// <param name="button">A <see cref="ExceptionWindowResult"/> value that 
        /// specifies the button or buttons to display.</param>
        /// <param name="icon">A <see cref="ExceptionWindowImage"/> value that
        /// specifies the icon to display.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Window owner,
            Exception exception,
            string caption,
            ExceptionWindowButton button,
            ExceptionWindowImage icon)
        {
            return Show(owner, exception, caption, button, icon, ExceptionWindowResult.Abort);
        }

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="owner">The window that will own the modal window.</param>
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the 
        /// title bar caption to display.</param>
        /// <param name="button">A <see cref="ExceptionWindowResult"/> value that 
        /// specifies the button or buttons to display.</param>
        /// <param name="icon">A <see cref="ExceptionWindowImage"/> value that
        /// specifies the icon to display.</param>
        /// <param name="defaultResult">A <see cref="ExceptionWindowResult"/> value
        /// that specifies the default result of the exception window.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Window owner,
            Exception exception,
            string caption,
            ExceptionWindowButton button,
            ExceptionWindowImage icon,
            ExceptionWindowResult defaultResult)
        {
            return Show(owner, exception, caption, button, icon, defaultResult, ExceptionWindowOptions.None);
        }
        #endregion

        #region Show
        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Exception exception)
        {
            return Show(null, exception);
        }

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the 
        /// title bar caption to display.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Exception exception,
            string caption)
        {
            return Show(null, exception, caption);
        }

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the 
        /// title bar caption to display.</param>
        /// <param name="button">A <see cref="ExceptionWindowResult"/> value that 
        /// specifies the button or buttons to display.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Exception exception,
            string caption,
            ExceptionWindowButton button)
        {
            return Show(null, exception, caption, button);
        }

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the 
        /// title bar caption to display.</param>
        /// <param name="button">A <see cref="ExceptionWindowResult"/> value that 
        /// specifies the button or buttons to display.</param>
        /// <param name="icon">A <see cref="ExceptionWindowImage"/> value that
        /// specifies the icon to display.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Exception exception,
            string caption,
            ExceptionWindowButton button,
            ExceptionWindowImage icon)
        {
            return Show(null, exception, caption, button, icon);
        }

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the 
        /// title bar caption to display.</param>
        /// <param name="button">A <see cref="ExceptionWindowResult"/> value that 
        /// specifies the button or buttons to display.</param>
        /// <param name="icon">A <see cref="ExceptionWindowImage"/> value that
        /// specifies the icon to display.</param>
        /// <param name="defaultResult">A <see cref="ExceptionWindowResult"/> value
        /// that specifies the default result of the exception window.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Exception exception,
            string caption,
            ExceptionWindowButton button,
            ExceptionWindowImage icon,
            ExceptionWindowResult defaultResult)
        {
            return Show(null, exception, caption, button, icon, defaultResult);
        }

        /// <summary>
        /// Displays an exception window infront of the main window.
        /// The exception window displays information and returns a result.
        /// </summary>
        /// <exception cref="ArgumentNullException">Occurs when the exception parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Occurs when the ApartmentState of the current thread (after marshalling) is not STA.</exception>        
        /// <param name="exception">A <see cref="System.Exception"/> that specifies 
        /// the information to display.</param>
        /// <param name="caption">A <see cref="System.String"/> that specifies the 
        /// title bar caption to display.</param>
        /// <param name="button">A <see cref="ExceptionWindowResult"/> value that 
        /// specifies the button or buttons to display.</param>
        /// <param name="icon">A <see cref="ExceptionWindowImage"/> value that
        /// specifies the icon to display.</param>
        /// <param name="defaultResult">A <see cref="ExceptionWindowResult"/> value
        /// that specifies the default result of the exception window.</param>
        /// <param name="options">A <see cref="ExceptionWindowOptions"/> value that
        /// specifies the options.</param>
        /// <returns>A <see cref="ExceptionWindowResult"/>.</returns>
        public static ExceptionWindowResult Show(
            Exception exception,
            string caption,
            ExceptionWindowButton button,
            ExceptionWindowImage icon,
            ExceptionWindowResult defaultResult,
            ExceptionWindowOptions options)
        {
            return Show(null, exception, caption, button, icon, defaultResult, options);
        }

        #endregion
    }
}
